home *** CD-ROM | disk | FTP | other *** search
- /* SUPPORT.C
- ************************************************************************
- * *
- * PC Scheme/Geneva 4.00 Borland C code *
- * *
- * (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- * (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- * *
- *----------------------------------------------------------------------*
- * *
- * Scheme Support (General) *
- * *
- *----------------------------------------------------------------------*
- * *
- * Created by: John Jensen Date: 1985 *
- * Revision history: *
- * - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- * *
- * ``In nomine omnipotentii dei'' *
- ************************************************************************/
-
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include <dir.h>
- #include "scheme.h"
- #include <bios.h>
-
- /************************************************************************/
- /* Substring */
- /************************************************************************/
- int ssubstr(REGPTR string, REGPTR start_reg, REGPTR end_reg)
- {
- unsigned str_page, str_disp;
- int i;
-
- str_page = CORRPAGE(string->page);
- str_disp = string->disp;
-
- /* validate input arguments */
- i = get_word(str_page, str_disp + 1);
- if (i < 0)
- i = i + BLK_OVHD + sizeof(POINTER); /* adjust for small string */
- if (ptype[str_page] == STRTYPE &&
- start_reg->page == ADJPAGE(SPECFIX) &&
- end_reg->page == ADJPAGE(SPECFIX) &&
- end_reg->disp >= start_reg->disp &&
- end_reg->disp <= i - BLK_OVHD) { /* arguments o.k.-- allocate new
- * string and copy substring characters */
- alloc_block(&tmp_reg, STRTYPE, end_reg->disp - start_reg->disp );
- msubstr(&tmp_reg, string, start_reg->disp, end_reg->disp );
- string->page = tmp_reg.page;
- string->disp = tmp_reg.disp;
- } else { /* invalid arguments to substring */
- set_src_error("SUBSTRING", 3, string, start_reg, end_reg);
- return -1;
- }
- return 0;
- }
-
- /************************************************************************/
- /* Test if two pointers are equal? */
- /************************************************************************/
- sequal_p(REGPTR reg1, REGPTR reg2)
- {
- REG r1 = *reg1, r2 = *reg2;
-
- checkstack(); /* Check to make sure we haven't recursed too deeply */
-
- while( gettype(&r1) == LISTTYPE ) /* do lists tail-recursively */
- {
- REG car1 = r1, car2 = r2;
-
- /* Quick test in case the pointers are "eq?" */
- if( eq( &r1, &r2 ) )
- return TRUE;
-
- if( gettype(&r2) != LISTTYPE )
- return FALSE;
-
- if( !r1.page || !r2.page ) /* if one is nil, speed up */
- return !r2.page && !r1.page;
-
- take_car(&car1), take_car(&car2);
- if( !sequal_p( &car1, &car2 ) )
- return FALSE;
- take_cdr(&r1), take_cdr(&r2);
- }
- /* now we've got atoms, so really do the compare */
-
- /* Quick test in case the pointers are "eq?" */
- if( eq( &r1, &r2 ) )
- return TRUE;
-
- if( gettype(&r1) != gettype(&r2) )
- return FALSE;
-
- switch( gettype(&r1) )
- {
- case FLOTYPE:
- return reg2c(&r1)->flonum.data == reg2c(&r2)->flonum.data;
- case BIGTYPE:
- case STRTYPE:
- return mcmpstr( reg1, reg2 );
- case VECTTYPE: /* test each entry of the arrays for equality */
- {
- VECTOR far *v1 = ®2c(&r1)->vector, far *v2 = ®2c(&r2)->vector;
-
- if( v1->len != v2->len )
- return FALSE;
- for( int i = 0; i < v1->len / sizeof(POINTER) - 1; i++ )
- {
- REG elem1, elem2;
-
- elem1.page = v1->data[i].page, elem1.disp = v1->data[i].disp;
- elem2.page = v2->data[i].page, elem2.disp = v2->data[i].disp;
-
- if( !sequal_p( &elem1, &elem2 ) )
- return FALSE;
- v1 = ®2c(&r1)->vector, v2 = ®2c(&r2)->vector;
- /* reload them, just for sure */
- }
- return TRUE;
- }
- default: /* For these types, assume that "eq?-ness" is enough */
- return FALSE;
- }
- }
-
- /************************************************************************/
- /* String->Symbol */
- /************************************************************************/
- int str_2_sym(REGPTR reg)
- {
- unsigned page, disp;
- int len;
- char *string;
-
- page = CORRPAGE(reg->page);
- disp = reg->disp;
- if (ptype[page] != STRTYPE) {
- set_src_error("STRING->SYMBOL", 1, reg);
- return -1;
- } else {
- len = get_word(page, disp + 1);
- if (len < 0)
- len = len + BLK_OVHD + sizeof(POINTER); /* adjust for small
- * string */
- len -= BLK_OVHD;
- if (!(string = (char *) malloc(len + 1)))
- malloc_error("str_2_sym");
- get_str(string, page, disp);
- string[len] = '\0';
- intern(reg, string, len);
- rlsstr(string);
- }
- return 0;
- }
-
- /************************************************************************/
- /* String->Uninterned-symbol */
- /************************************************************************/
- int str_2_usym(REGPTR reg)
- {
- unsigned page;
- int len;
- char *string;
-
- page = CORRPAGE(reg->page);
- if (ptype[page] != STRTYPE) {
- set_src_error("STRING->UNINTERNED-SYMBOL", 1, reg);
- return -1;
- } else {
- len = get_word(page, reg->disp + 1);
- if (len < 0)
- len = len + BLK_OVHD + sizeof(POINTER); /* adjust for small string */
- len -= BLK_OVHD;
- if (!(string = (char *) malloc(len + 1)))
- malloc_error("str_2_usym");
- get_str(string, page, reg->disp);
- string[len] = '\0';
- alloc_sym(reg, len);
- put_sym(string, CORRPAGE(reg->page), reg->disp, ADJPAGE(NIL_PAGE), NIL_DISP, 0);
- rlsstr(string);
- }
- return 0;
- }
-
- /************************************************************************/
- /* Symbol->String */
- /************************************************************************/
- int sym_2_str(REGPTR reg)
- {
- unsigned page;
- char *string;
-
- page = CORRPAGE(reg->page);
- if (ptype[page] != SYMTYPE) {
- set_src_error("SYMBOL->STRING", 1, reg);
- return -1;
- } else {
- string = symbol_name(page, reg->disp);
- alloc_string(reg, string);
- rlsstr(string);
- }
-
- return 0;
- }
-
- /************************************************************************/
- /* Retrieve Symbol Name */
- /* */
- /* Purpose: To fetch the print name of a symbol from Scheme's memory */
- /* and return it in a C string. */
- /************************************************************************/
- char *symbol_name(unsigned page, unsigned disp)
- {
- char *name = NULL;
- int length; /* length of symbol + 1 (characters) */
-
- if (ptype[page] == SYMTYPE) {
- length = get_word(page, disp + 1) - (BLK_OVHD + sizeof(POINTER));
- if (!(name = (char *) malloc(length)))
- malloc_error("symbol_name");
- get_sym(name, page, disp);
- name[length - 1] = '\0';
- }
- return name;
- }
-
- /************************************************************************/
- /* Retrieve String Value */
- /* */
- /* Purpose: To fetch the value of a string from Scheme's memory */
- /* and return it in a C string. */
- /************************************************************************/
- char *string_asciz(REGPTR reg)
- {
- char *name = NULL;
- unsigned page;
- int length;
-
- page = CORRPAGE(reg->page);
-
- if (ptype[page] == STRTYPE) {
- length = get_word(page, reg->disp + 1);
- if (length < 0)
- length = length + BLK_OVHD + sizeof(POINTER);
- length = length - BLK_OVHD + 1;
- if (!(name = (char *) malloc(length)))
- malloc_error("string_asciz");
- get_str(name, page, reg->disp);
- name[length - 1] = '\0';
- }
- return name;
- }
-
- /************************************************************************/
- /* Release String */
- /* */
- /* Purpose: To release the memory allocated to a C character */
- /* string. If the string is null, the free is skipped. */
- /************************************************************************/
- void rlsstr(char *string)
- {
- if (string) /* is the string allocated? */
- free(string);
- else
- zprintf("ERROR: string null released");
- }
-
- /************************************************************************/
- /* Convert Scheme Integer to C Long Integer */
- /* */
- /* Purpose: To obtain the value of a Scheme integer (up to 32 bits) */
- /* for manipulation by the C support routines. */
- /* */
- /* Description: Given a Scheme pointer to an integer value, this */
- /* routine returns the long integer corresponding to */
- /* the value of the Scheme integer. */
- /* */
- /* Calling Sequence: long = int2long(value) */
- /* where value - address of location where the long */
- /* integer result is to be stored. */
- /* ptr - a Scheme register address containing the */
- /* Scheme representation of the integer */
- /* value. */
- /* stat - return code; 0 = no errors, value returned */
- /* 1 = error, integer too large or ptr */
- /* was not an integer. */
- /************************************************************************/
- long int2long(REGPTR reg)
- {
- if( ptype[CORRPAGE(reg->page)] == BIGTYPE )
- {
- SCHEMEOBJ o = reg2c(reg);
- long l;
-
- l = o->bignum.data.data[0];
- if( o->bignum.data.len > 6 )
- l += ((long) o->bignum.data.data[1]) << 16;
- if( o->bignum.data.sign )
- l = -l;
- return l;
- }
- else return reg->disp; /* assume it's a fixnum */
- }
-
-
- /************************************************************************/
- /* Convert C Long Integer to Scheme Integer */
- /* */
- /* Purpose: To convert a C long integer value to the equivalent */
- /* Scheme representation. */
- /* */
- /* Description: Given a long integer value, this routine creates the */
- /* equivalent Scheme integer object and returns it in the */
- /* designated register. */
- /* */
- /* Calling Sequence: long2int(reg, value) */
- /* where value - the Borland C long integer value to be converted */
- /* to Scheme representation */
- /* reg - a Scheme register address to hold the result. */
- /************************************************************************/
- void long2int(REGPTR reg, long value)
- {
- /* determine if value can be represented as a fixnum */
- if (value < 32768 && value >= -32768)
- reg->page = ADJPAGE(SPECFIX), reg->disp = value;
- else enlarge(reg, value);
- }
-
- /************************************************************************/
- /* Convert C Boolean to correct scheme representation */
- /* */
- /************************************************************************/
- void bool2scm(REGPTR reg, int value)
- {
- if( value ) {
- reg->page = ADJPAGE(T_PAGE);
- reg->disp = T_DISP;
- } else
- *reg = nil_reg;
- }
-
- /************************************************************************/
- /* Convert scheme Boolean to C boolean */
- /* */
- /************************************************************************/
- int scm2bool(REGPTR reg)
- {
- return eq( reg, &nil_reg );
- }
-
- /************************************************************************/
- /* Calculate the true length of a scheme string */
- /* */
- /************************************************************************/
- int regstrlen(REGPTR str)
- {
- int len = ( reg2c(str)->string.len );
-
- if( len < 0 )
- len += sizeof(POINTER);
- else
- len -= BLK_OVHD;
-
- return len;
- }
-
- /************************************************************************/
- /* Append two lists */
- /************************************************************************/
- int sappend(REGPTR dest, REGPTR src)
- {
- REG car;
- int saved = FALSE; /* Whether a list copy has been pushed */
-
- c_push(src);
- c_push(src);
- tm2_reg = *dest; /* save destination operand, in case of error */
- while (dest->page && ptype[CORRPAGE(dest->page)] == LISTTYPE) {
- if (s_break)
- restart(3); /* shift-break? if so, start over */
- take_car(&(car = *dest));
- cons(src, &car, &nil_reg);
- if (!saved) {
- c_push(src);
- saved = TRUE;
- } else {
- asetcdr(&tmp_reg, src);
- }
- tmp_reg = *src;
- take_cdr(dest);
- }
- if (dest->page) {
- if (saved)
- c_pop(src);
- c_pop(src);
- c_pop(src); /* Restore old SRC */
- set_src_error("APPEND", 2, &tm2_reg, src);
- return -1;
- }
- c_pop(dest);
- if (saved) {
- c_pop(&tmp_reg); /* Retrieve 2nd arg to append */
- asetcdr(src, &tmp_reg);
- }
- c_pop(src); /* Restore old SRC */
- return 0;
- }
-
- /************************************************************************/
- /* Start PCS Engine Timer */
- /************************************************************************/
- int cset_tim(REGPTR value)
- {
- unsigned hi, lo; /* parts of 32-bit value for timer */
- unsigned page; /* page and displacement in register */
- page = CORRPAGE(value->page);
- hi = 0;
- switch ( ptype[page] ) {
- case BIGTYPE:
- switch (get_word(page, value->disp + 1)) {
- case 8:
- hi = get_word(page, value->disp + 6);
- case 6:
- lo = get_word(page, value->disp + 4);
- break;
- default:
- hi = lo = 0xffff;
- break;
- }
- break;
- case FIXTYPE:
- lo = value->disp;
- break;
- default:
- set_src_error("%START-TIMER", 1, value);
- }
- if (!settimer(hi, lo)) {
- set_error(1, "Timer already running", &nil_reg);
- return -1;
- }
- return 0;
- }
-
- /************************************************************************/
- /* Stop PCS Engine Timer and Return Value */
- /************************************************************************/
- void crst_tim(REGPTR value)
- {
- long2int( value, rsttimer() );
- }
-
-
- /************************************************************************/
- /* Support for I-search in an environment */
- /************************************************************************/
- char *pcsrsenv = "PCS-RESERVED-SYMBOLS-ENVIRONMENT";
- char *pcsksenv = "PCS-KNOWN-SYMBOLS-ENVIRONMENT";
-
- void get_maxenv( REGPTR kn_env )
- {
- intern( kn_env, pcsksenv, strlen( pcsksenv ) );
- if ( !( sym_lookup(kn_env, &gnv_reg) && (ptype[CORRPAGE(kn_env->page)] == ENVTYPE) ) ) {
- intern( kn_env, pcsrsenv, strlen( pcsrsenv ) );
- if ( !( sym_lookup( kn_env, &gnv_reg) && (ptype[CORRPAGE(kn_env->page)] == ENVTYPE) ) )
- *kn_env = gnv_reg;
- }
- return;
- }
-
- /************************************************************************/
- /* Support for I-search in an environment */
- /************************************************************************/
- REG lastfound;
-
- void matchdone( void )
- {
- lastfound = nil_reg; // helps the garbage collector
- }
-
- char *matchsym( char *symbolstr, int fixlen, REGPTR sym, REGPTR pair, int *previous_found )
- {
- char *symbol;
- int pos;
-
- symbol = symbol_name( CORRPAGE(sym->page), sym->disp );
- for ( pos = 0; (toupper(symbolstr[pos]) == toupper(symbol[pos])) &&
- ((pos < fixlen) || !*previous_found) &&
- (symbolstr[pos] != 0); pos++ );
-
- if ( (symbol[pos] != 0) && (pos >= fixlen) && *previous_found )
- {
- int symlower = 0;
-
- for ( pos = 0; symbolstr[pos] != 0; pos++ )
- symlower |= islower(symbolstr[pos]);
- if ( symlower ) strlwr(symbol);
- lastfound = *pair;
- take_cdr( pair );
- tmp_reg = *sym;
- tm2_reg = *pair;
- return symbol;
- }
-
- if ( (symbolstr[pos] == 0) && (symbol[pos] == 0) && eq( &lastfound, pair ) )
- *previous_found = 1;
- rlsstr(symbol);
- return NULL;
- }
-
- /************************************************************************/
- /* I-search in an environment (or prop list if special env is used) */
- /* Calling sequence: found = ilookup( symbolstr, fixlen, page, disp ) */
- /* where symbolstr - a ptr to null-terminated string */
- /* fixlen - the number of character to be matched */
- /* page, disp - of the environment to search */
- /* Returns the name of the binding found (stored in tmp_reg . tm2_reg) */
- /************************************************************************/
- char *ilookup( char *symbolstr, int fixlen, unsigned page, unsigned disp )
- {
- int previous_found = ( _fstrlen( symbolstr ) == fixlen );
- char *result;
- REG proplist;
- int in_proplist;
-
- intern( &proplist, pcsrsenv, strlen( pcsrsenv ) ); /* find factice environment */
- sym_lookup( &proplist, &gnv_reg );
-
- while( page )
- {
- SCHEMEOBJ currenv = scheme2c( page, disp );
- POINTER parent = currenv->environment.parent;
-
- in_proplist = ( (page == CORRPAGE(proplist.page)) && (disp == proplist.disp) );
-
- if ( (currenv->environment.len == sizeof(ENVIRONMENT)) && !in_proplist )
- { /* rib format */
- POINTER names = currenv->environment.names;
- POINTER values = currenv->environment.values;
- REG nam, val;
- REG sym;
-
- nam.page = names.page; nam.disp = names.disp;
- val.page = values.page; val.disp = values.disp;
- while ( nam.page )
- {
- sym = nam;
- take_car(&sym);
- result = matchsym(symbolstr, fixlen, &sym, &val, &previous_found);
- if ( result ) return result;
- take_cdr(&nam);
- take_car(&val);
- }
- } else { /* hash table format */
- for (int j = 0; j < HT_SIZE; j++)
- {
- REG search, pair, sym;
-
- if ( in_proplist ) {
- parent.page = gnv_reg.page; /* gnv_reg is updated */
- parent.disp = gnv_reg.disp;
- search.page = prop_page[j]; /* prop list also */
- search.disp = prop_disp[j];
- } else {
- currenv = scheme2c( page, disp + j * sizeof(POINTER) );
- search.page = currenv->environment.names.page;
- search.disp = currenv->environment.names.disp;
- }
-
- while( search.page )
- {
- pair = search;
- take_car(&pair);
- sym = pair;
- take_car(&sym);
-
- result = matchsym(symbolstr, fixlen, &sym, &pair, &previous_found);
- if ( result ) return result;
- take_cdr(&search);
- }
- }
- }
-
- page = CORRPAGE(parent.page); disp = parent.disp;
- }
-
- return NULL; /* not found */
- }
-
- /************************************************************************/
- /* I-search for a DOS filename */
- /* Calling sequence: found = ifile( symbolstr, fixlen ) */
- /* where symbolstr - a ptr to null-terminated string */
- /* fixlen - the number of character to be matched */
- /* Returns the name or NULL if no completion exists */
- /************************************************************************/
- char *ifile( char *symbolstr, int fixlen )
- {
- static struct find_t ffblk;
- char *pattn, *path;
- char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT];
- int stat;
-
- if( !(pattn = (char *)malloc(fixlen+4)) ||
- !(path = (char *)malloc(MAXPATH+1)) )
- malloc_error("ifile");
-
- strncpy(pattn, symbolstr, fixlen); // calculate file pattern
- pattn[fixlen] = 0;
- if( fnsplit( pattn, drive, dir, NULL, NULL ) & EXTENSION )
- strcpy( pattn+fixlen, "*");
- else strcpy( pattn+fixlen, "*.*");
-
- if( strlen(symbolstr) == fixlen ) // search directory
- stat = _dos_findfirst( pattn, FA_DIREC, &ffblk);
- else
- stat = _dos_findnext( &ffblk );
-
- while( !stat && ffblk.name[0] == '.' )
- stat = _dos_findnext( &ffblk );
-
- if( stat ) {
- strncpy( path, symbolstr, fixlen );
- path[fixlen] = 0;
- } else {
- fnsplit( ffblk.name, NULL, NULL, name, ext );
- fnmerge( path, drive, dir, name, ext );
- if( ffblk.attrib & FA_DIREC )
- strcat( path, "/");
- else strcat( path, "\"");
- if( strlen(path) == fixlen ) // if same as root, add space
- strcpy( path+fixlen, " ");
- {
- char *scan = symbolstr;
- while(*scan && !isalpha(*scan)) scan++;
- if( islower( scan[0] ) || islower( scan[1] ) )
- strlwr( path ); // translate to lower case
- }
- }
-
- rlsstr(pattn);
- return path;
- }
-
- /************************************************************************/
- /* Scheme-Reset */
- /************************************************************************/
- void scheme_reset(void)
- {
- unsigned car_page, car_disp;
- int i;
- unsigned page, disp;
-
- /* create a pointer to the symbol "scheme-top-level" */
- intern(&tmp_reg, "SCHEME-TOP-LEVEL", 16);
-
- /* If first call to Scheme-reset, initialize state parameters */
- if (!fp_save) {
- fp_save = frameptr;
- page = CORRPAGE(fnv_save.page = fnv_reg.page);
- disp = fnv_save.disp = fnv_reg.disp;
-
- /* find the binding for "scheme-top-level" */
- while (page) {
- car_page = CORRPAGE(get_byte(page, disp));
- car_disp = get_word(page, disp + 1);
- if (tmp_reg.disp == get_word(car_page, car_disp + 1) &&
- tmp_reg.page == get_byte(car_page, car_disp)) {
- stl_save.page = get_byte(car_page, car_disp + 3);
- stl_save.disp = get_word(car_page, car_disp + 4);
- break;
- }
- i = CORRPAGE(get_byte(page, disp + 3));
- disp = get_word(page, disp + 4);
- page = i;
- }
-
- if (!page) { /* if "scheme-top-level" not in fluids, error */
- print_and_exit(
- "[VM FATAL ERROR] No fluid binding for SCHEME-TOP-LEVEL\n");
- }
- } else {
- /* Reset fluid environment */
- page = CORRPAGE(fnv_reg.page = fnv_save.page);
- disp = fnv_reg.disp = fnv_save.disp;
-
- /* find the binding for "scheme-top-level" */
- while (page) {
- car_page = CORRPAGE(get_byte(page, disp));
- car_disp = get_word(page, disp + 1);
- if (tmp_reg.disp == get_word(car_page, car_disp + 1) &&
- tmp_reg.page == get_byte(car_page, car_disp)) {
- put_ptr(car_page, car_disp + 3, stl_save.page, stl_save.disp);
- break;
- }
- i = CORRPAGE(get_byte(page, disp + 3));
- disp = get_word(page, disp + 4);
- page = i;
- }
- }
- }
-
- /************************************************************************/
- /* Reification Support */
- /************************************************************************/
- int reify( int direction, REGPTR obj, REGPTR index, REGPTR val )
- {
- SCHEMEOBJ o;
-
- if( index->page != ADJPAGE(SPECFIX) )
- {
- if( direction )
- set_src_error("%REIFY!", 3, obj, index, val);
- else
- set_src_error("%REIFY", 2, obj, index);
- return -1;
- }
-
- o = reg2c(obj);
-
- switch( ptype[CORRPAGE(obj->page)] )
- {
- case LISTTYPE:
- if( !direction )
- obj->page = ADJPAGE(SPECFIX), obj->disp = sizeof(LIST);
- break;
- case FIXTYPE:
- case CHARTYPE:
- if( !direction )
- obj->page = ADJPAGE(SPECFIX), obj->disp = sizeof(POINTER);
- break;
- case FLOTYPE:
- if( index->disp == 0xffff )
- obj->page = ADJPAGE(SPECFIX), obj->disp = sizeof(FLONUM);
- else if( direction )
- {
- long l;
- l = int2long( obj );
- ((unsigned far *) &o->flonum.data)[index->disp] = l;
- }
- else long2int( obj, ((unsigned far *) &o->flonum.data)[index->disp] );
- break;
- default:
- POINTER far *p;
- p = ((POINTER far *) o) + index->disp + 1;
-
- if( index->disp == 0xffff )
- obj->page = ADJPAGE(SPECFIX), obj->disp = o->_.len;
- else if( direction )
- p->page = val->page, p->disp = val->disp;
- else obj->page = p->page, obj->disp = p->disp;
- break;
- }
- return 0;
- }
-
- #define NUM_SPEC 6
-
- /* This code shouldn't be move into a procedure, or Borland C will call
- REG::REG every 65536th call to intern... */
-
- static char *special_constants[NUM_SPEC] =
- {"#T", "#F", "#!FALSE", "#!NULL", "#!TRUE", "#!UNASSIGNED"};
- static REG spec_reg[NUM_SPEC] = {
- REG( T_DISP, ADJPAGE(T_PAGE) ),
- REG( NIL_DISP, ADJPAGE(NIL_PAGE) ),
- REG( NIL_DISP, ADJPAGE(NIL_PAGE) ),
- REG( NIL_DISP, ADJPAGE(NIL_PAGE) ),
- REG( T_DISP, ADJPAGE(T_PAGE) ),
- REG( UN_DISP, ADJPAGE(UN_PAGE) ) };
-
- void intern(REGPTR reg, char *string, int length)
- {
- unsigned disp; /* displacement of the symbol's entry */
- unsigned hash_value; /* value returned from hashing function */
- int i, j;
- unsigned page;
- char *ptr; /* pointer to special constant name */
-
- if (string[0] == '#') {
- for (i = 0; i < NUM_SPEC; i++) {
- if( length == strlen(special_constants[i]) ) {
- for (j = 0, ptr = special_constants[i]; j < length; j++)
- if (string[j] != *ptr++)
- goto no_match;
- *reg = spec_reg[i];
- return;
- }
- no_match:;
- }
- }
- hash_value = hash(string, length);
- if (hash_page[hash_value] != 0) {
- page = CORRPAGE(hash_page[hash_value]);
- disp = hash_disp[hash_value];
- while (page != 0) {
- if (sym_eq(page, disp, string, length)) {
- reg->page = ADJPAGE(page);
- reg->disp = disp;
- return;
- }
- /* Follow hash chain link pointer to next symbol */
- i = CORRPAGE(get_byte(page, disp + 3));
- disp = get_word(page, disp + 4);
- page = i;
- }
- }
- /* add symbol to oblist */
- alloc_sym(reg, length);
- page = CORRPAGE(reg->page);
- put_sym(string, page, reg->disp, hash_page[hash_value], hash_disp[hash_value],
- hash_value);
- hash_page[hash_value] = reg->page;
- hash_disp[hash_value] = reg->disp;
- }
-
- /************************************************************************
- * A New getch() *
- ************************************************************************/
- static char previous = 0;
-
- char GETCH(void)
- {
- int temp;
-
- if( previous )
- {
- int save = previous;
- previous = 0;
- return save;
- }
-
- temp = bioskey( 0 );
- if( (temp & 0xff) == 0 )
- previous = temp >> 8;
- return temp & 0xff;
- }
-
- int GETCHready(void)
- {
- int temp;
- if( previous )
- return previous;
- else {
- int temp = bioskey( 1 );
- if( !(temp & 0xff) )
- return (temp & 0xff00) != 0;
- else return temp & 0xff;
- }
- }